﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;
using SPDevLab.WebParts.JsAppWebPart.Apps;
using SPDevLab.WebParts.JsAppWebPart.Client;
using SPDevLab.WebParts.JsAppWebPart.Consts;
using SPDevLab.WebParts.JsAppWebPart.Services;
using SPDevLab.WebParts.JsAppWebPart.Services.Base;
using System.Text;
using SPDevLab.WebParts.Extensions;

namespace SPDevLab.WebParts.JsAppWebPart
{
    [ToolboxItemAttribute(false)]
    public class JsApplicationWebPart : WebPart
    {
        #region web part properties

        [WebBrowsable(false),
            Category("Js App settings"),
            Personalizable(PersonalizationScope.Shared),
            WebDisplayName("Js App settings."),
            WebDescription("Allows to setup JSON settings for the selected JS App.")]
        public string JsApplicationOptions { get; set; }

        #endregion

        #region properties

        private Literal _jsAppContentControl = new Literal();
        private JsAppServiceBase _jsAppService;

        public virtual JsAppServiceBase JsAppService
        {
            get { return _jsAppService ?? (_jsAppService = new DefaultJsAppService()); }
        }

        #endregion

        #region methods

        protected virtual void ApplyJsApplicationContent(string jsAppOptions)
        {
            if (SPContext.Current != null)
            {
                var site = SPContext.Current.Site;
                var jsAppSettings = JsAppService.DeserializeFromJson<JsAppOptionsContext>(jsAppOptions);

                var app = JsAppService.LoadLastActiveApp(site, jsAppSettings.SelectedAppFolderPath);

                if (app != null && !string.IsNullOrEmpty(app.AppHtmlContent))
                {
                    var appTokens = new List<JsAppToken>();

                    appTokens.AddRange(JsAppService.GetLinkedJsAppTokens(site));
                    appTokens.AddRange(JsAppService.GetLinkedJsAppTokens(this));
                    appTokens.AddRange(JsAppService.GetLinkedJsAppTokens(app));

                    _jsAppContentControl.Text = JsAppService.CreateAppHtmlContent(app.AppHtmlContent, appTokens);
                }
            }
            else
            {
                // TODO
                // a better and friendly message to setup the web part within SPContext
            }
        }

        protected override void CreateChildControls()
        {
            if (!string.IsNullOrEmpty(JsApplicationOptions))
            {
                try
                {
                    Controls.Add(_jsAppContentControl);

                    ApplyJsApplicationContent(JsApplicationOptions);
                }
                catch (Exception createChildControlsException)
                {
                    Controls.Add(new Literal { Text = createChildControlsException.ToString() });
                }
            }
            else
            {
                var htmlBuffer = new StringBuilder();

                htmlBuffer.Append("There is no JS App configured for the current web part.<br/>");
                htmlBuffer.Append("Please, <a href=\"javascript:MSOTlPn_ShowToolPane2Wrapper('Edit', this, '" + ID + "')\">open the toolpanel</a> to setup the app.");

                Controls.Add(new Literal { Text = htmlBuffer.ToString() });
            }
        }

        public string GetJsAppOptionsContextAsJson()
        {
            var result = new JsAppOptionsContext();

            if (!string.IsNullOrEmpty(JsApplicationOptions))
                result = JsAppService.DeserializeFromJson<JsAppOptionsContext>(JsApplicationOptions);

            if (SPContext.Current != null)
            {
                var rootWeb = SPContext.Current.Web.Site.RootWeb;

                result.RootWebUrl = rootWeb.ServerRelativeUrl;
                result.JsAppFolderUrl = SPUrlUtility.CombineUrl(rootWeb.ServerRelativeUrl, JsAppConsts.Urls.AppLibraryUrl);
            }

            result.ContainerId = ClientID + JsAppConsts.ClientIdPostfix.ToolpartId;

            return JsAppService.SerializeToJson(result);
        }

        public override EditorPartCollection CreateEditorParts()
        {
            var result = base.CreateEditorParts()
                                    .OfType<EditorPart>()
                                    .ToList();

            var jsAppEditorPart = new JsApplicationEditorPart { ID = string.Format("{0}_{1}", ID, "JsAppEditorPart") };

            result.Insert(0, jsAppEditorPart);

            return new EditorPartCollection(result);
        }

        public void SetJsAppOptionsContext(string appTitle, string appUrl)
        {
            var result = new JsAppOptionsContext();

            if (!string.IsNullOrEmpty(JsApplicationOptions))
                result = JsAppService.DeserializeFromJson<JsAppOptionsContext>(JsApplicationOptions);

            result.SelectedAppTitle = appTitle;
            result.SelectedAppFolderPath = appUrl;

            JsApplicationOptions = JsAppService.SerializeToJson(result);

            ApplyJsApplicationContent(JsApplicationOptions);
        }

        #endregion
    }
}
